package com.soft.bams.service;

import com.soft.bams.dao.FileDao;
import com.soft.bams.dao.IDao;
import com.soft.bams.entity.*;
import com.soft.bams.exception.*;
import com.soft.bams.server.ServerTask;
import com.soft.bams.vo.RankVO;


import javax.swing.*;
import java.util.*;

/**
 * @author yzh
 * @desc TODO
 * @date 2025/4/17
 */
public class Bank {
    private static Bank instance = new Bank();
    private IDao<Account, List<Account>> dao;

    private Bank() {
        this.dao = new FileDao();
    }

    public static Bank getInstance() {
        return instance;
    }

    public IDao<Account, List<Account>> getDao() {
        return dao;
    }

    // 用户开户
    public Account register(String password, String repassword, String name,
                            String personID, String email, int type) throws RegisterException, TypeException {
        if (password == null || repassword == null || password.equals("") || repassword.equals("")) {
            //System.out.println("密码不能为空！");


            throw new RegisterException("密码不能为空");
            //return null;
        }
        if (!password.equals(repassword)) {
            //System.out.println("两次密码不一致！");
            throw new RegisterException("两次密码不一致！");
            //return null;
        }

        Long id = dao.createId();
        if (id == -1L) {
            throw new RegisterException("本月开卡名额已用完");
        }

        Account account;
        switch (type) {
            case 0: // 储蓄账户
                account = new SavingAccount(id, password, name, personID, email, 0.0);
                break;
            case 1: // 信用账户
                account = new CreditAccount(id, password, name, personID, email, 0.0, 1000.0); // 默认透支额度1000
                break;
            case 2: // 可贷款储蓄账户
                account = new LoanSavingAccount(id, password, name, personID, email, 0);
                break;
            case 3: // 可贷款信用账户
                account = new LoanCreditAccount(id, password, name, personID, email, 0, 1000);
                break;
            default:
                //System.out.println("不支持的账户类型");
                throw new TypeException("不支持的账户类型");
                //return null;
        }

        if (!dao.insert(account)) {
            throw new RegisterException("开户失败");
        }
        return account;
    }

    // 用户登录
    public Account login(Long id, String password) throws LoginException {
        if (id == null || password == null || password.equals("")) {
            throw new LoginException("账户或密码不能为空");
            //return null;
        }
        Account account = dao.selectOne(id, password);
        if (account != null) {
            //System.out.println("登陆成功");
            JOptionPane.showMessageDialog(null,"登陆成功");
        } else {
            //System.out.println("账户或密码错误");
            throw new LoginException("账户或密码错误");
        }
        return account;
    }

    // 用户存款
    public Account deposit(Long id, double money) throws LoginException, NotFoundException {
        if (id == null) {
            throw new LoginException("账户不能为空");
            //return null;
        }
        Account account = dao.selectOne(id);
        if (account != null) {
            account.deposit(money);
            dao.update(account);
            return dao.selectOne(id);
        }
        throw new NotFoundException("账户不存在");
        //return null;
    }

    // 用户取款
    public Account withdraw(Long id, String password, double money) throws BalanceNotEnoughException, LoginException {
        if (id == null || password == null || password.equals("")) {
            throw new LoginException("账户或密码不能为空");
            //return null;
        }
        Account account = dao.selectOne(id, password);
        if (account != null) {
            account.withdraw(money);
            dao.update(account);
            return dao.selectOne(id);
        }
        throw new LoginException("账户或密码错误");
        //return null;
    }

    // 设置透支额度
    public Account updateCeiling(Long id, String password, double money) throws TypeException, LoginException {
        if (id == null || password == null || password.equals("")) {
            throw new LoginException("账户或密码不能为空");
            //return null;
        }
        Account account = dao.selectOne(id, password);
        if (account instanceof CreditAccount) {
            ((CreditAccount) account).setCeiling(money);
            dao.update(account);
            return dao.selectOne(id);
        }
        /*System.out.println("只有信用账户可以设置透支额度");
        return null;*/
        throw new TypeException("只有信用账户可以设置透支额度");
    }

    // 转账功能
    public boolean transfer(Long from, String passwordFrom, Long to, double money) throws BalanceNotEnoughException, MoneyException, NotFoundException {
        if (money <= 0) {
            /*System.out.println("转账金额必须大于0");
            return false;*/
            throw new MoneyException("转账金额必须大于0");
        }

        Account fromAccount = dao.selectOne(from, passwordFrom);
        Account toAccount = dao.selectOne(to);

        if (fromAccount == null || toAccount == null) {
            /*System.out.println("账户不存在");
            return false;*/
            throw new NotFoundException("账户不存在或密码错误");
        }

        if (fromAccount.getId().equals(toAccount.getId())) {
            throw new NotFoundException("不能转账给自己");
            /*System.out.println("不能转账给自己");
            return false;*/
        }

        // 检查转出账户余额是否足够
        boolean canWithdraw = false;
        if (fromAccount instanceof CreditAccount) {
            CreditAccount creditFrom = (CreditAccount) fromAccount;
            canWithdraw = (fromAccount.getBalance() + creditFrom.getCeiling()) >= money;
        } else {
            canWithdraw = fromAccount.getBalance() >= money;
        }

        if (!canWithdraw) {
            /*System.out.println("转出账户余额不足");
            return false;*/
            throw new BalanceNotEnoughException("转出账户余额不足");
        }

        // 执行转账操作
        fromAccount.withdraw(money);
        toAccount.deposit(money);

        dao.update(fromAccount);
        dao.update(toAccount);

        //System.out.println("转账成功");
        return true;
    }

    // 统计银行所有账户余额总数
    public double getTotalBalance() {
        double total = 0;
        List<Account> accounts = dao.selectAll();
        for (Account acc : accounts) {
            if (acc != null) {
                total += acc.getBalance();
            }
        }
        return total;
    }

    // 统计所有信用账户透支额度总数
    public double getTotalCeiling() {
        double total = 0;
        List<Account> accounts = dao.selectAll();
        for (Account acc : accounts) {
            if (acc instanceof CreditAccount) {
                total += ((CreditAccount) acc).getCeiling();
            }
        }
        return total;
    }

    // 贷款
    public Account requestLoan(Long id, double money) throws LoanException, TypeException, LoginException {
        if (id == null) {
            throw new LoginException("账户不能为空");
            //return null;
        }
        Account account = dao.selectOne(id);
        if (account instanceof Loanable) {
            ((Loanable) account).requestLoan(money);
            dao.update(account);
            return dao.selectOne(id);
        }
        /*System.out.println("该账户不支持贷款");
        return null;*/
        throw new TypeException("该账户不支持贷款");

    }

    // 还贷
    public Account payLoan(Long id, double money) throws BalanceNotEnoughException, TypeException, LoginException {
        if (id == null) {
            throw new LoginException("账户不能为空");
            //return null;
        }
        Account account = dao.selectOne(id);
        if (account instanceof Loanable) {
            ((Loanable) account).payLoan(money);
            dao.update(account);
            return dao.selectOne(id);
        }
        /*System.out.println("该账户不支持贷款");
        return null;*/
        throw new TypeException("该账户不支持贷款");
    }

    // 统计所有贷款总额
    public double getTotalLoan() {
        double total = 0;
        List<Account> accounts = dao.selectAll();
        for (Account acc : accounts) {
            if (acc instanceof LoanSavingAccount) {
                total += ((LoanSavingAccount) acc).getLoanAmount();
            } else if (acc instanceof LoanCreditAccount) {
                total += ((LoanCreditAccount) acc).getLoanAmount();
            }
        }
        return total;
    }

    // 打印所有用户的总资产排名
    public Set<RankVO> printAssetRank() {
        List<Account> allAccounts = dao.selectAll();

        Map<String, RankVO> map = new HashMap<>();

        for (Account account : allAccounts) {
            String personId = account.getPersonId();
            double balance = account.getBalance();
            String name = account.getName();

            if (map.containsKey(personId)) {
                map.put(personId, new RankVO(personId,name,balance+map.get(personId).getTotal()));
            } else {
                map.put(personId,new RankVO(personId,name,balance));
            }
        }

        Set<RankVO> set = new TreeSet<>();
        for (Map.Entry<String, RankVO> entry : map.entrySet()) {
            set.add(entry.getValue());
        }

        System.out.println("------------ 用户总资产排名 ------------");
        System.out.println("排名\t身份证号\t\t\t\t\t总资产");
        int rank = 1;
        for (RankVO vo : set) {
            System.out.println((rank++) + "\t" + vo.getPersonId()+"\t\t"+vo.getTotal());
        }
        return set;
    }

    public Set<Map.Entry<Long, String>> getLoggedAccountsInfo() {
        return ServerTask.getLoggedAccounts().entrySet();
    }
}